﻿using Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace Service
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ServerOnline" in both code and config file together.
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class ServerServices : IServerServices
    {
        static List<ICheckerClient> clients = new List<ICheckerClient>();
        static List<string> clientsName = new List<string>();
        static List<string> inGameClient = new List<string>();
        Methods methods = new Methods();
        public ServerServices()
        {

        }

        public bool IsOnline()
        {
            return System.Diagnostics.Debugger.IsAttached;
        }

        public StepServiceResponse StepProcess(StepRequest request)
        {
            StepServiceResponse response = methods.PerformStepProcess(request);
            if(response.Code == 108 || response.Code==109 || response.Code==116)
            {

                int index = clientsName.IndexOf(response.Opponent);
                if(index==-1)
                {
                    response.Opponent = (char.ToUpper(response.Opponent[0]) + response.Opponent.Substring(1)).ToString();
                    index = clientsName.IndexOf(response.Opponent);
                }
                try
                {
                    if (index != -1)
                        clients.ElementAt(index).StepChangeProcess(request, response);
                }
                catch (Exception)
                {
                    clients.RemoveAt(index);
                    return response;
                } 
            }
            if(response.Code == 115)
            {
                int index = clientsName.IndexOf(response.Opponent);
                try
                {
                    if (index != -1)
                        clients.ElementAt(index).GameResultChangeProcess(request.UserID, 1);
                }
                catch (Exception)
                {
                    clients.RemoveAt(index);
                    return response;
                }
            }
            return response;
        }

        public SendMsgServiceResponse SendMsgProcess(SendMsgRequest request)
        {
            SendMsgServiceResponse response = methods.PerformSendMsgProcess(request);
            if (response.Code == 106)
            {
                int index = clientsName.IndexOf(response.Username);
                try
                {
                    if (index != -1)
                        clients.ElementAt(index).GetMsgChangeProcess(response.Username);
                }
                catch (Exception)
                {
                    clients.RemoveAt(index);
                    return response;
                }
                
            }
            return response;
        }

        public RegistrationServiceResponse RegistrationProcess(RegistrationRequest request)
        {
            return methods.PerformRegistrationProcess(request);
        }

        public NewGameServiceResponse NewGameProcess(NewGameRequest request)
        {
            NewGameServiceResponse response = methods.PerformNewGameProcess(request);
            if (response.Code == 104)
            {
                inGameClient.Add(request.Username);
                int i = 0;
                try
                {
                    foreach (var item in clients)
                    {
                        if (!inGameClient.Contains(clientsName.ElementAt(i)))
                            item.ListGameChangeProcess();
                        i++;
                    }
                }
                catch (Exception)
                {
                    clients.RemoveAt(i);
                    return response;
                }
                
            }
            return response;
        }

        public LogoutServiceResponse LogoutProcess(LogoutRequest request)
        {
            LogoutServiceResponse response = methods.PerformLogoutProcess(request);
            if (response.Code == 111)
            {
                int index = clientsName.IndexOf(request.UserName);
                try
                {
                    if (index != -1)
                    {
                        clients.RemoveAt(index);
                        clientsName.RemoveAt(index);
                    }
                }
                catch (Exception)
                {
                    clients.RemoveAt(index);
                    return response;
                }
                
            }
            return response;
        }

        public LoginServiceResponse LoginProcess(LoginRequest request)
        {
            LoginServiceResponse response = methods.PerformLoginProcess(request);
            if (response.Code == 101)
            {
                ICheckerClient client = OperationContext.Current.GetCallbackChannel<ICheckerClient>();
                if (!clients.Contains(client))
                {
                    clients.Add(client);
                    clientsName.Add(request.UserName);
                }
            }
            return response;
        }

        public ListGameServiceResponse ListGameProcess(ListGameRequest request)
        {
            ListGameServiceResponse response = methods.PerformListGameProcess(request);
            return response;
        }

        public JoinGameServiceResponse JoinGameProcess(JoinGameRequest request)
        {
            JoinGameServiceResponse response = methods.PerformJoinGameProcess(request);
            if (response.Code == 103)
            {
                int i = -2;
                int index = -2;
                try
                {
                    inGameClient.Add(request.UserName);
                    index = clientsName.IndexOf(response.Opponent);
                    
                    if (index != -1)
                    {
                        clients.ElementAt(index).StartGameChangeProcess(request.UserName);
                        i = 0;
                        foreach (var item in clients)
                        {
                            if (!inGameClient.Contains(clientsName.ElementAt(i)))
                                item.ListGameChangeProcess();
                            i++;
                        }
                    }
                }
                catch (Exception)
                {
                    if(i==-2)
                    {
                        clients.RemoveAt(index);
                    }
                    else
                    {
                        clients.RemoveAt(i);
                    }
                    return response;
                }
                
            }
            return response;
        }

        public GiveUpServiceResponse GiveUpProcess(GiveUpRequest request)
        {
            GiveUpServiceResponse response = methods.PerformGiveUpProcess(request);
            if (response.Code == 107)
            {
                int index = -2;
                try
                {
                    index = clientsName.IndexOf(response.Opponent);
                    if (index != -1)
                    {
                        if (response.Opponent == request.UserID)
                        {
                            clients.ElementAt(index).GameResultChangeProcess(response.Opponent, 3);
                        }
                        else
                        {
                            clients.ElementAt(index).GameResultChangeProcess(response.Opponent, 2);
                        }
                    }
                }
                catch (Exception)
                {
                    clients.RemoveAt(index);
                    return response;
                }
                
            }
            return response;
        }

        public GetMsgServiceResponse GetMsgProcess(GetMsgRequest request)
        {
            return methods.PerformGetMsgProcess(request);
        }

        public CloseGameServiceResponse CloseGameProcess(CloseGameRequest request)
        {
            CloseGameServiceResponse response = methods.PerformCloseGameProcess(request);
            if (response.Code == 110)
            {
                int i = 0;
                try
                {
                    
                    foreach (var item in clients)
                    {
                        if (!inGameClient.Contains(clientsName.ElementAt(i)))
                            item.ListGameChangeProcess();
                        i++;
                    }
                }
                catch (Exception)
                {
                    clients.RemoveAt(i);
                    return response;
                }
               
            }
            return response;
        }

        public PlayerStatsServiceResponse PlayerStatsProcess(PlayerStatsRequest request)
        {
            return methods.PerformPlayerStatsProcess(request);
        }

    }
}
